home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 19
/
Aminet 19 (1997)(GTI - Schatztruhe)[!][Jun 1997].iso
/
Aminet
/
util
/
blank
/
GBLvshuf.lha
/
LivingShuffle
/
Dev
/
blank.c
next >
Wrap
C/C++ Source or Header
|
1997-04-07
|
31KB
|
729 lines
/*
* Copyright (c) 1997 Ingo Schmiegel
* All rights reserved.
*
*/
#include <exec/memory.h>
#include "/includes.h"
#include <clib/intuition_protos.h>
#include <intuition/intuitionbase.h>
#include <math.h>
#include <time.h>
#define PREFS_UPDATE 0 /* update the pieces or simple shuffle */
#define PREFS_HORIZ 2 /* number of columns in the puzzle */
#define PREFS_VERT 4 /* number of rows in the puzzle */
#define PREFS_DIVIS 6 /* number of steps for one shuffle movement */
#define PREFS_HOLE 8 /* hole filling mode */
#define PREFS_BORDER 10 /* draw border around the pieces? */
#define PREFS_DELAY 12 /* delay between two such steps */
#define PREFS_SCREEN 14 /* select from which screen cloning should take place */
#define PREFS_FADEPCT 16 /* percent of brightness of the original colours */
#define PREFS_UPDATE_YES 0
#define PREFS_UPDATE_NO 1
#define PREFS_HOLE_BACKGROUND 0
#define PREFS_HOLE_ONCERANDOM 1
#define PREFS_HOLE_RANDOM 2
#define PREFS_BORDER_YES 0
#define PREFS_BORDER_NO 1
#define PREFS_SCREEN_FRONT 0
#define PREFS_SCREEN_PUBLIC 1
#include "LivingShuffle_rev.h"
STATIC const UBYTE VersTag[] = VERSTAG;
/* maximum puzzle pieces */
#define PUZZLE_MAX_ROWS 50
#define PUZZLE_MAX_COLUMNS 50
/* minimum piece size (rows and columns values will be adjusted) (MUST BE AT LEAST 4!!) */
#define PIECE_MIN_WIDTH 8
#define PIECE_MIN_HEIGHT 8
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* Piece - describing one piece of the puzzle
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
typedef struct _Piece
{
long srcx; /* source topleft coordinate (in columns and rows) */
long srcy; /* the destination coordinate is its position in the puzzle array */
} Piece;
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* Puzzle - describing the puzzle
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
enum _direction { up, down, left, right };
typedef enum _direction direction;
typedef struct _Puzzle
{
long columns; /* Size (columns,rows) */
long rows;
long steps; /* steps to do during one piece movement */
long pw; /* Size of one piece in pixels */
long ph;
struct Screen *srcscr; /* source screen (only screen pointer here for SAFETY!) */
struct RastPort *destrp; /* destination screen's rastport */
Piece pieces[PUZZLE_MAX_ROWS][PUZZLE_MAX_COLUMNS]; /* Array of pieces */
BOOL doborder;
/* these values are updated before a new shuffle is started */
long hx; /* hole position */
long hy;
long step; /* actual step */
long from; /* direction of actual movement (fill hole with piece from <from> direction) */
} Puzzle;
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
Puzzle puzzle;
const long ColBack = 0; /* Background colour */
const long ColDarkEdge = 1; /* Colour of the bottom right dark edges */
const long ColBrightEdge = 2; /* Colour of the top left bright edges */
long ColHole; /* Is once (or more often) randomly selected by main() */
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
void Defaults(PrefObject *Prefs)
{
Prefs[PREFS_UPDATE].po_Level = PREFS_UPDATE_YES;
Prefs[PREFS_HORIZ].po_Level = 10;
Prefs[PREFS_VERT].po_Level = 8;
Prefs[PREFS_DIVIS].po_Level = 10;
Prefs[PREFS_HOLE].po_Active = PREFS_HOLE_BACKGROUND;
Prefs[PREFS_BORDER].po_Active = PREFS_BORDER_YES;
Prefs[PREFS_DELAY].po_Level = 1;
Prefs[PREFS_SCREEN].po_Active = PREFS_SCREEN_FRONT;
Prefs[PREFS_FADEPCT].po_Level = 25;
}
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* OpenLibs "Open all needed libraries"
*
* Result: TRUE or FALSE
*
* Function: Opens the needed libraries
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
BOOL OpenLibs(void)
{
return TRUE;
}
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* CloseLibs "Close all needed libraries"
*
* Function: Closes all opened libraries
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
void CloseLibs(void)
{
}
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* RndBT (macro) "Random from Bottom to Top"
*
* Parameters: min The minimum of possible random numbers (any of: int,char,word,long; no floats!)
* max The maximum of possible random numbers (dito)
* (Do not use negative numbers!)
*
* Result: long A random number
*
* Function: Returns a random number in the interval of [min..max] (both included)
*
* Note: Call srand48() once before using this function to set a seek value,
* e.g.: srand48(time(NULL))
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
#define RndBT(min,max) ((min)+(lrand48()%((max)-(min)+1)))
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* DrawRectBorder "Draw the border of one rectangle"
*
* Parameters: left edge, top edge, right edge, bottom edge
*
* Result: none
*
* Function: Draws a frame around a rectangle, light shines from the top left
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
void DrawRectBorder (long xl, long yt, long xr, long yb)
{
SetAPen(puzzle.destrp,ColDarkEdge);
Move(puzzle.destrp,xr,yt);
Draw(puzzle.destrp,xr,yb);
Draw(puzzle.destrp,xl,yb);
SetAPen(puzzle.destrp,ColBrightEdge);
Draw(puzzle.destrp,xl,yt);
Draw(puzzle.destrp,xr,yt);
}
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* getNewDir "Get a new direction"
*
* Parameters: none
*
* Result: none
*
* Function: sets the direction field in the puzzle, so that the next shuffle movement
* can be done.
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
void getNewDir(void)
{ /* pos of hole , grid dimensions , last movemetn direction */
direction dir;
for(;;)
{
dir=(direction)RndBT(0,3);
switch (dir)
{
case left: if (puzzle.hx == 0) break; /* try again */
if (puzzle.from == right) break; /* try again */
puzzle.from = dir; return;
case right: if (puzzle.hx == (puzzle.columns-1)) break; /* try again */
if (puzzle.from == left) break; /* try again */
puzzle.from = dir; return;
case up: if (puzzle.hy == 0) break; /* try again */
if (puzzle.from == down) break; /* try again */
puzzle.from = dir; return;
case down: if (puzzle.hy == (puzzle.rows-1)) break; /* try again */
if (puzzle.from == up) break; /* try again */
puzzle.from = dir; return;
}
}
}
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* initPuzzle "Initialize the puzzle"
*
* Parameters:
*
* Result: none
*
* Function: Initializes all fields
*
* Note: Ever call this function with valid screen pointers !!!
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
void initPuzzle (struct Screen *src, struct Screen *dest, long columns, long rows, long steps)
{
long r,c;
puzzle.columns = columns;
puzzle.rows = rows;
puzzle.steps = steps;
puzzle.pw = dest->Width / columns;
puzzle.ph = dest->Height / rows;
puzzle.srcscr = src;
puzzle.destrp = &(dest->RastPort);
puzzle.hx = RndBT(0,columns-1);
puzzle.hy = RndBT(0,rows-1);
puzzle.step = 0;
puzzle.from = (direction)RndBT(0,3);
getNewDir(); /* to do bordercorrections */
/* Initialize the pieces */
for (r=0;r<rows;r++)
{
for (c=0;c<columns;c++)
{
puzzle.pieces[r][c].srcx = c;
puzzle.pieces[r][c].srcy = r;
if (puzzle.doborder)
DrawRectBorder( c*puzzle.pw, r*puzzle.ph, (c+1)*puzzle.pw-1, (r+1)*puzzle.ph-1 );
}
}
if (puzzle.doborder)
{
/* Now draw a nice right border puzzle (which isn't shuffled, because it's too small) */
if ((columns*puzzle.pw) < (dest->Width-2))
{ /* enough room for a nice right border */
for (r=0;r<rows;r++)
DrawRectBorder(columns*puzzle.pw, r*puzzle.ph,
dest->Width-1, (r+1)*puzzle.ph-1);
}
else if ((columns*puzzle.pw) < dest->Width)
{ /* not enough room for a nice right border but a background strip */
SetAPen(puzzle.destrp,ColBack);
RectFill(puzzle.destrp,
columns*puzzle.pw, 0,
dest->Width-1, dest->Height-1);
}
/* Now draw a nice bottom border puzzle (which isn't shuffled, because it's too small) */
if ((rows*puzzle.ph) < (dest->Height-2))
{ /* enough room for a nice bottom border */
for (c=0;c<columns;c++)
DrawRectBorder(c*puzzle.pw, rows*puzzle.ph,
(c+1)*puzzle.pw-1, dest->Height-1);
/* test if the bottom right edge can be drawn with a border */
if ((columns*puzzle.pw) < (dest->Width-2))
{ /* enough room for a nice bottom right border */
DrawRectBorder(columns*puzzle.pw, rows*puzzle.ph,
dest->Width-1, dest->Height-1);
}
}
else if ((rows*puzzle.ph) < dest->Height)
{ /* not enough room for a nice bottom border but a background strip */
SetAPen(puzzle.destrp,ColBack);
RectFill(puzzle.destrp,
0, rows*puzzle.ph,
dest->Width-1, dest->Height-1);
}
}
/* At last clear the hole piece */
SetAPen(puzzle.destrp,ColHole);
RectFill(puzzle.destrp, puzzle.hx*puzzle.pw, puzzle.hy*puzzle.ph,
(puzzle.hx+1)*puzzle.pw-1, (puzzle.hy+1)*puzzle.ph-1);
}
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* doStep "Do one step of movement"
*
* Parameters: none
*
* Result: none
*
* Function: Redraws the whole puzzle with one step of movement done
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
void doStep (void)
{
long r,c; /* row, column counter */
long px,py; /* piece which is currently moving */
long dx,dy; /* piece's moving offset */
long pxl,pxr,pyt,pyb; /* dest coordinates */
BOOL onemovecompleted = FALSE;
switch (puzzle.from)
{
case down: dx = 0;
dy = - puzzle.ph * puzzle.step / puzzle.steps;
px = puzzle.hx;
py = puzzle.hy+1;
break;
case up: dx = 0;
dy = puzzle.ph * puzzle.step / puzzle.steps;
px = puzzle.hx;
py = puzzle.hy-1;
break;
case right: dx = - puzzle.pw * puzzle.step / puzzle.steps;
dy = 0;
px = puzzle.hx+1;
py = puzzle.hy;
break;
case left: dx = puzzle.pw * puzzle.step / puzzle.steps;
dy = 0;
px = puzzle.hx-1;
py = puzzle.hy;
break;
}
for (r=0;r<puzzle.rows;r++)
{
for (c=0;c<puzzle.columns;c++)
{
if ((r == puzzle.hy) && (c == puzzle.hx)) /* HOLE */
{
/* nothing to do, 'cause the hole is slowly filled by the moving piece */
}
else
{
if ((r == py) && (c == px)) /* MOVE */
{
/* update the moving piece */
BltBitMap(puzzle.srcscr->RastPort.BitMap,
(puzzle.pieces[r][c].srcx)*puzzle.pw,
(puzzle.pieces[r][c].srcy)*puzzle.ph,
puzzle.destrp->BitMap,
pxl = c*puzzle.pw+dx,
pyt = r*puzzle.ph+dy,
puzzle.pw,
puzzle.ph,
0xc0,0xff,NULL);
if (puzzle.doborder)
{
pxr = pxl + puzzle.pw-1;
pyb = pyt + puzzle.ph-1;
DrawRectBorder(pxl,pyt,pxr,pyb); /* draw the border of this piece */
}
/* fill the new hole (erase the old piece data there) */
if (dx || dy)
{
long xtl,ytl,xbr,ybr; /* new hole's rectangular coordinates */
switch (puzzle.from)
{
case left: xtl = c * puzzle.pw;
xbr = c * puzzle.pw + dx - 1;
ytl = r * puzzle.ph;
ybr = r * puzzle.ph + puzzle.ph - 1;
break;
case right: xtl = c * puzzle.pw + puzzle.pw + dx;
xbr = c * puzzle.pw + puzzle.pw - 1;
ytl = r * puzzle.ph;
ybr = r * puzzle.ph + puzzle.ph - 1;
break;
case up: ytl = r * puzzle.ph;
ybr = r * puzzle.ph + dy - 1;
xtl = c * puzzle.pw;
xbr = c * puzzle.pw + puzzle.pw - 1;
break;
case down: ytl = r * puzzle.ph + puzzle.ph + dy;
ybr = r * puzzle.ph + puzzle.ph - 1;
xtl = c * puzzle.pw;
xbr = c * puzzle.pw + puzzle.pw - 1;
break;
}
SetAPen(puzzle.destrp,ColHole);
RectFill(puzzle.destrp,xtl,ytl,xbr,ybr);
}
if (++puzzle.step > puzzle.steps) onemovecompleted = TRUE;
}
else /* STILL */
{
if (puzzle.doborder)
{
/* do a simple actualizing (first without border) */
BltBitMap(puzzle.srcscr->RastPort.BitMap, /* source bitmap */
(puzzle.pieces[r][c].srcx)*puzzle.pw+1,
(puzzle.pieces[r][c].srcy)*puzzle.ph+1, /* src coord */
puzzle.destrp->BitMap, /* dest bitmap */
(pxl=c*puzzle.pw)+1,
(pyt=r*puzzle.ph)+1, /* dest coord */
puzzle.pw-2,
puzzle.ph-2, /* piece size without border */
0xc0,0xff,NULL); /* minterm, planemask,tempbuf */
/* now add the border */
pxr = pxl + puzzle.pw -1;
pyb = pyt + puzzle.ph -1;
DrawRectBorder(pxl,pyt,pxr,pyb);
}
else
{
/* do a simple actualizing */
BltBitMap(puzzle.srcscr->RastPort.BitMap, /* source bitmap */
(puzzle.pieces[r][c].srcx)*puzzle.pw,
(puzzle.pieces[r][c].srcy)*puzzle.ph, /* src coord */
puzzle.destrp->BitMap, /* dest bitmap */
c*puzzle.pw,
r*puzzle.ph, /* dest coord */
puzzle.pw,
puzzle.ph, /* piece size */
0xc0,0xff,NULL); /* minterm, planemask,tempbuf */
}
}
}
}
}
if (onemovecompleted)
{ /* swap hole and last moving piece */
puzzle.pieces[puzzle.hy][puzzle.hx].srcx = puzzle.pieces[py][px].srcx;
puzzle.pieces[puzzle.hy][puzzle.hx].srcy = puzzle.pieces[py][px].srcy;
switch (puzzle.from)
{
case down: puzzle.hy++; break;
case up: puzzle.hy--; break;
case left: puzzle.hx--; break;
case right: puzzle.hx++; break;
}
/* select new direction */
getNewDir();
puzzle.step = 0;
}
}
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* initSimplePuzzle "Initialize only the parts of the puzzle needed for simple shuffling"
*
* Parameters:
*
* Result: none
*
* Function: Initializes all fields
*
* Note: Ever call this function with valid screen pointers !!!
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
void initSimplePuzzle (struct Screen *dest, long columns, long rows, long steps)
{
long r,c;
puzzle.columns = columns;
puzzle.rows = rows;
puzzle.steps = steps;
puzzle.pw = dest->Width / columns;
puzzle.ph = dest->Height / rows;
puzzle.srcscr = NULL;
puzzle.destrp = &(dest->RastPort);
puzzle.hx = RndBT(0,columns-1);
puzzle.hy = RndBT(0,rows-1);
puzzle.step = 0;
puzzle.from = (direction)RndBT(0,3);
getNewDir(); /* to do bordercorrections */
if (puzzle.doborder)
{
/* Draw the pieces' border */
for (r=0;r<rows;r++)
for (c=0;c<columns;c++)
DrawRectBorder( c*puzzle.pw, r*puzzle.ph, (c+1)*puzzle.pw-1, (r+1)*puzzle.ph-1 );
/* Now draw a nice right border puzzle (which isn't shuffled, because it's too small) */
if ((columns*puzzle.pw) < (dest->Width-2))
{ /* enough room for a nice right border */
for (r=0;r<rows;r++)
DrawRectBorder(columns*puzzle.pw, r*puzzle.ph,
dest->Width-1, (r+1)*puzzle.ph-1);
}
else if ((columns*puzzle.pw) < dest->Width)
{ /* not enough room for a nice right border but a background strip */
SetAPen(puzzle.destrp,ColBack);
RectFill(puzzle.destrp,
columns*puzzle.pw, 0,
dest->Width-1, dest->Height-1);
}
/* Now draw a nice bottom border puzzle (which isn't shuffled, because it's too small) */
if ((rows*puzzle.ph) < (dest->Height-2))
{ /* enough room for a nice bottom border */
for (c=0;c<columns;c++)
DrawRectBorder(c*puzzle.pw, rows*puzzle.ph,
(c+1)*puzzle.pw-1, dest->Height-1);
/* test if the bottom right edge can be drawn with a border */
if ((columns*puzzle.pw) < (dest->Width-2))
{ /* enough room for a nice bottom right border */
DrawRectBorder(columns*puzzle.pw, rows*puzzle.ph,
dest->Width-1, dest->Height-1);
}
}
else if ((rows*puzzle.ph) < dest->Height)
{ /* not enough room for a nice bottom border but a background strip */
SetAPen(puzzle.destrp,ColBack);
RectFill(puzzle.destrp,
0, rows*puzzle.ph,
dest->Width-1, dest->Height-1);
}
}
/* At last clear the hole piece */
SetAPen(puzzle.destrp,ColHole);
RectFill(puzzle.destrp, puzzle.hx*puzzle.pw, puzzle.hy*puzzle.ph,
(puzzle.hx+1)*puzzle.pw-1, (puzzle.hy+1)*puzzle.ph-1);
}
/*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*
* doSimpleStep "Do one step of movement just shuffling no updating"
*
* Parameters: none
*
* Result: none
*
* Function: Redraws the whole puzzle with one step of movement done
*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*°*/
void doSimpleStep (void)
{
long px,py; /* piece which is currently moving */
long dx,dy; /* piece's moving offset */
long olddx,olddy; /* piece's last moving offset */
long pxl,pxr,pyt,pyb; /* dest coordinates */
switch (puzzle.from)
{
case down: dx = 0;
dy = - puzzle.ph * puzzle.step / puzzle.steps;
olddx = 0;
if (puzzle.step) olddy = - puzzle.ph * (puzzle.step-1) / puzzle.steps;
else olddy = 0;
px = puzzle.hx;
py = puzzle.hy+1;
break;
case up: dx = 0;
dy = puzzle.ph * puzzle.step / puzzle.steps;
olddx = 0;
if (puzzle.step) olddy = puzzle.ph * (puzzle.step-1) / puzzle.steps;
else olddy = 0;
px = puzzle.hx;
py = puzzle.hy-1;
break;
case right: dx = - puzzle.pw * puzzle.step / puzzle.steps;
dy = 0;
if (puzzle.step) olddx = - puzzle.pw * (puzzle.step-1) / puzzle.steps;
else olddx = 0;
olddy = 0;
px = puzzle.hx+1;
py = puzzle.hy;
break;
case left: dx = puzzle.pw * puzzle.step / puzzle.steps;
dy = 0;
if (puzzle.step) olddx = puzzle.pw * (puzzle.step-1) / puzzle.steps;
else olddx = 0;
olddy = 0;
px = puzzle.hx-1;
py = puzzle.hy;
break;
}
/* update the moving piece */
BltBitMap(puzzle.destrp->BitMap, px*puzzle.pw+olddx, py*puzzle.ph+olddy,
puzzle.destrp->BitMap, pxl = px*puzzle.pw+dx, pyt = py*puzzle.ph+dy,
puzzle.pw, puzzle.ph,
0xc0,0xff,NULL);
if (puzzle.doborder)
{
pxr = pxl + puzzle.pw-1;
pyb = pyt + puzzle.ph-1;
DrawRectBorder(pxl,pyt,pxr,pyb); /* draw the border of this piece */
}
/* fill the new hole (erase the old piece data there) */
if (dx || dy)
{
long xtl,ytl,xbr,ybr; /* new hole's rectangular coordinates */
switch (puzzle.from)
{
case left: xtl = px * puzzle.pw;
xbr = px * puzzle.pw + dx - 1;
ytl = py * puzzle.ph;
ybr = py * puzzle.ph + puzzle.ph - 1;
break;
case right: xtl = px * puzzle.pw + puzzle.pw + dx;
xbr = px * puzzle.pw + puzzle.pw - 1;
ytl = py * puzzle.ph;
ybr = py * puzzle.ph + puzzle.ph - 1;
break;
case up: ytl = py * puzzle.ph;
ybr = py * puzzle.ph + dy - 1;
xtl = px * puzzle.pw;
xbr = px * puzzle.pw + puzzle.pw - 1;
break;
case down: ytl = py * puzzle.ph + puzzle.ph + dy;
ybr = py * puzzle.ph + puzzle.ph - 1;
xtl = px * puzzle.pw;
xbr = px * puzzle.pw + puzzle.pw - 1;
break;
}
SetAPen(puzzle.destrp,ColHole);
RectFill(puzzle.destrp,xtl,ytl,xbr,ybr);
}
if (++puzzle.step > puzzle.steps)
{ /* move hole */
switch (puzzle.from)
{
case down: puzzle.hy++; break;
case up: puzzle.hy--; break;
case left: puzzle.hx--; break;
case right: puzzle.hx++; break;
}
/* select new direction */
getNewDir();
puzzle.step = 0;
}
}
/************************************************************************************************/
/************************************************************************************************/
/************************************************************************************************/
LONG Blank( PrefObject *Prefs )
{
long RetVal, ToFrontCount = 0;
struct Screen *srcscr,*destscr;
struct Window *win;
long Rows,Columns,Steps,StepDelay;
long i,delay;
Columns = Prefs[PREFS_HORIZ].po_Level;
Rows = Prefs[PREFS_VERT].po_Level;
Steps = Prefs[PREFS_DIVIS].po_Level;
StepDelay = Prefs[PREFS_DELAY].po_Level;
srand48(time(NULL)); /* Set seek value for Unix's lrand48() function */
/* lrand48() provides a number from 0..2**31 */
if (OpenLibs())
{
if (Prefs[PREFS_UPDATE].po_Active == PREFS_UPDATE_YES)
{
/* get source screen pointer */
if (Prefs[PREFS_SCREEN].po_Active==PREFS_SCREEN_PUBLIC)
{
srcscr = LockPubScreen(0L);
UnlockPubScreen(0L,srcscr);
}
else
if (Prefs[PREFS_SCREEN].po_Active==PREFS_SCREEN_FRONT)
{
ULONG lock = LockIBase(0);
srcscr = IntuitionBase->FirstScreen;
UnlockIBase(lock);
}
else srcscr=NULL;
}
else srcscr=NULL;
if(destscr=cloneTopScreen(FALSE,Prefs[PREFS_SCREEN].po_Active))
{
if (Prefs[PREFS_HOLE].po_Active == PREFS_HOLE_BACKGROUND)
ColHole = ColBack;
else ColHole = RndBT(0,(1L<<destscr->RastPort.BitMap->Depth)-1); /* choose a colour randomly */
if ((destscr->Width/Columns) < PIECE_MIN_WIDTH) Columns = destscr->Width/PIECE_MIN_WIDTH;
if ((destscr->Height/Rows) < PIECE_MIN_HEIGHT) Rows = destscr->Height/PIECE_MIN_HEIGHT;
if ((Columns>=2) && (Rows>=2))
{
/* adjust steps if necessary */
if ((destscr->Width/Columns/2) <= Steps) Steps = destscr->Width/Columns / 2;
if ((destscr->Height/Rows/2) <= Steps) Steps = destscr->Height/Rows / 2;
if (srcscr || (Prefs[PREFS_UPDATE].po_Active==PREFS_UPDATE_NO))
{
if(Prefs[PREFS_FADEPCT].po_Level)
{
ULONG *ColorTable, PctCount, BPG;
ColorTable = GetColorTable(destscr);
BPG = AvgBitsPerGun(getTopScreenMode());
PctCount = (1L<<BPG) * Prefs[PREFS_FADEPCT].po_Level/100;
for(i=0;i<PctCount;i++) FadeAndLoadTable(destscr,BPG,ColorTable,0);
}
puzzle.doborder = (Prefs[PREFS_BORDER].po_Active==PREFS_BORDER_YES)? TRUE:FALSE;
if (Prefs[PREFS_UPDATE].po_Active == PREFS_UPDATE_YES)
initPuzzle(srcscr,destscr,Columns,Rows,Steps); /* fetch gfx data from src scr */
else initSimplePuzzle(destscr,Columns,Rows,Steps); /* simple shuffling */
win = BlankMousePointer(destscr);
delay = StepDelay;
while((RetVal=ContinueBlanking())==OK)
{
if(!(++ToFrontCount%64)) ScreenToFront(destscr);
if (--delay) Delay(1L); /* delay for one tick */
else
{
if (puzzle.step==0)
if (Prefs[PREFS_HOLE].po_Active == PREFS_HOLE_RANDOM)
ColHole = RndBT(0,(1L<<destscr->RastPort.BitMap->Depth)-1);
delay = StepDelay;
WaitTOF();
if (Prefs[PREFS_UPDATE].po_Active == PREFS_UPDATE_YES) doStep();
else doSimpleStep();
}
} /* end of while(RetVal==OK) */
UnblankMousePointer(win);
}
else RetVal = FAILED; /* couldn't get srcscr address */
}
else RetVal = FAILED; /* too less columns or rows */
CloseScreen(destscr);
}
else RetVal = FAILED;
}
else RetVal = FAILED;
CloseLibs();
return RetVal;
}